import { Request, Response } from 'express'
import i18n from '@/i18n'
import { AppLogger, AssistException } from '@libs/lhy-common'
import { ArgumentsHost, Catch, ExceptionFilter, HttpStatus } from '@nestjs/common'
import { CoreExceptionCode, CoreValidationException } from '../../exception'
import { CoreHttpException } from '../../exception/core-http.exception'

@Catch()
export class AllExceptionFilter implements ExceptionFilter<Error> {
  catch(error: Error, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const request = ctx.getRequest<Request>()
    const response = ctx.getResponse<Response>()

    // CoreValidationException
    if (error instanceof CoreValidationException) {
      return this.handleCoreHttpException(error.getI18nError(), error, host)
    }

    // CoreHttpException
    if (error instanceof CoreHttpException) {
      return this.handleCoreHttpException(error, error, host)
    }

    // AssistException
    if (error instanceof AssistException) {
      return this.handleCoreHttpException(
        new CoreHttpException(error.message, { code: error.code || CoreExceptionCode.Prompt }),
        error,
        host
      )
    }

    // 处理资源文件404 NotFound
    if ((error as any).code === 'ENOENT') {
      return this.handleCoreHttpException(
        new CoreHttpException(i18n.t('lhy-core.all-exception.all-exception.1214949-0', { args: [request.url] }), {
          status: HttpStatus.NOT_FOUND,
        }),
        error,
        host
      )
    }

    return this.handleCoreHttpException(new CoreHttpException(error), error, host)
  }

  protected handleCoreHttpException(exception: CoreHttpException, error: Error, host: ArgumentsHost) {
    AppLogger.error(AllExceptionFilter.name, exception, error)

    const ctx = host.switchToHttp()
    const response = ctx.getResponse<Response>()
    const request = ctx.getRequest<Request>()
    const status = exception.getStatus()

    response.status(status).json({
      status: status,
      code: exception.code,
      message: exception.message,
      timestamp: Date.now(),
      path: request.url,
    })
  }
}
